﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class UiOutPut : MonoBehaviour
{
    public int indent = 4;

    private ArrayList my_output = new ArrayList();

    // Start is called before the first frame update
    void Start()
    {
        LoadChild(this.transform, my_output);

        OutputElement();
    }

    private void LoadChild(Transform transform, ArrayList output)
    {
        int count = transform.childCount;
        for (int i = 0; i < count; i++)
        {
            Transform _transform = transform.GetChild(i);
            Dictionary<string, object> node = new Dictionary<string, object>();
            output.Add(node);
            AddingNodeParam(node,_transform);
        }
    }

    // 根据组件添加节点属性
    private void ProcessTypeElement(Dictionary<string, object> node, Transform _transform)
    {
        GameObject gameObject = _transform.gameObject;

        if(gameObject.TryGetComponent(out Button button))
        {
            AddingButtonParam(node, _transform);
        }
        else if(gameObject.TryGetComponent(out Image img))
        {
            AddingSpriteParam(node,_transform);
        }
        else if (gameObject.TryGetComponent(out Text text))
        {
            AddingLabelParam(node, _transform);
        }
        else
        { 
            node.Add("type", ValueString("node"));
        }
    }

    private void OutputElement()
    {
        using (StreamWriter sw = new StreamWriter("output.lua"))
        {
            sw.Write("local View = {width=1334,height=750,children={");

            ReadNode(my_output, sw, 0);

            sw.Write("}}");
        }
    }

    private void ReadNode(ArrayList node, StreamWriter sw, int space)
    {

        bool isHead_node = true;

        foreach (Dictionary<string, object> dic in node)
        {
            if (isHead_node)
            {
                isHead_node = false;
            }
            else
            {
                sw.Write(",");
            }
            sw.Write("\n");
            WriteSpace(space, sw);
            sw.Write("{\n");
            WriteSpace(space + indent, sw);

            bool isHead_param = true;
            String nodeType = (String)dic["type"];

            foreach (var item in dic)
            {


                string element = item.Key;
                object param = item.Value;

                if (element != "children")
                {
                    if(FilterKey(nodeType,element))
                    {
                        if (element == ValueString("type")) 
                        {
                            if ((String)param == ValueString("scale9sprite"))
                            {
                                param = ValueString("sprite");
                            }
                        }

                        if (element == "fontsize")
                        {
                            element = "size";
                        }

                        if (isHead_param)
                        {
                            isHead_param = false;
                        }
                        else
                        {
                            sw.Write(",");
                        }

                        // 换行检查
                        if(CheckWirteLine(nodeType,element))
                        {
                            sw.Write("\n");
                        }

                        sw.Write(element + "=" + param);
                    }
                }
                else
                {
                    ArrayList childrenList = (ArrayList)item.Value;
                    if (childrenList.Count > 0)
                    {

                        if (isHead_param)
                        {
                            isHead_param = false;
                        }
                        else
                        {
                            sw.Write(",");
                        }

                        sw.Write("children={");
                        ReadNode(childrenList, sw, space + indent + indent);
                        sw.Write("\n");
                        WriteSpace(space + indent, sw);
                        sw.Write("}");
                    }
                }
            }
            sw.Write("\n");
            WriteSpace(space, sw);
            sw.Write("}");
        }
    }

    private bool CheckWirteLine(String type,String key)
    {
        return false;
    }

    private bool FilterKey(String type,String key)
    {
        // print(type + ":" + key);
        if(key == "size")
        {
            if(type == ValueString("node") || type == ValueString("sprite") || type == ValueString("label"))
            {
                return false;
            }
        }
        return true;
    }

    private void WriteSpace(int count, StreamWriter sw)
    {
        for (int i = 0; i < count; i++)
        {
            sw.Write(" ");
        }
    }

    private string ValueString(string input)
    {
        string ret = "\"" + input + "\"";
        return ret;
    }

    private void SetAlignParam(Dictionary<string, object> node, Transform _transform)
    {
        GameObject gameObject = _transform.gameObject;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();

        Vector2 anchor = new Vector2(rectTransform.pivot.x, rectTransform.pivot.y);
        String anchorStr = "";

        Dictionary<string, Vector2> dicAnchor = new Dictionary<string, Vector2>();
        dicAnchor.Add("center", new Vector2(0.5f, 0.5f));
        dicAnchor.Add("left_top", new Vector2(0.0f, 1.0f));
        dicAnchor.Add("top", new Vector2(0.5f, 1.0f));
        dicAnchor.Add("right_top", new Vector2(1.0f, 1.0f));
        dicAnchor.Add("left", new Vector2(0.0f, 0.5f));
        dicAnchor.Add("right", new Vector2(1.0f, 0.5f));
        dicAnchor.Add("left_bottom", new Vector2(0.0f, 0.0f));
        dicAnchor.Add("right_bottom", new Vector2(1.0f, 0.0f));
        dicAnchor.Add("bottom", new Vector2(0.5f, 0.0f));

        foreach (var item in dicAnchor)
        {
            string key = item.Key;
            Vector2 tempAnchor = item.Value;

            if (anchor.Equals(tempAnchor))
            {
                anchorStr = key;
                break;
            }
        }

        if (anchorStr != "")
        {
            node.Add("align", "{" + ValueString(anchorStr) + "," + rectTransform.anchoredPosition3D.x + "," + rectTransform.anchoredPosition3D.y + "}");
        }
        else
        {
            // position
            node.Add("pos", "{" + (int)rectTransform.anchoredPosition3D.x + "," + (int)rectTransform.anchoredPosition3D.y + "}");
            //  anchor
            node.Add("anchor", "{" + rectTransform.pivot.x + "," + rectTransform.pivot.y + "}");
        }
    }

    private void AddingButtonParam(Dictionary<string, object> node, Transform _transform)
    {
        //node.Add("type", ValueString("button"));
        GameObject gameObject = _transform.gameObject;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        if (gameObject.TryGetComponent<Button>(out Button button)) 
        {
            if (button.transition == Button.Transition.None)
            {
                node.Add("type", ValueString("simple_btn"));
                if (gameObject.TryGetComponent<Image>(out Image image))
                {
                    node.Add("res", ValueString("#" + image.sprite.name + ".png"));
                }
            }
            else if (button.transition == Button.Transition.SpriteSwap) 
            {
                node.Add("type", ValueString("normal_btn"));
                if (gameObject.TryGetComponent<Image>(out Image image))
                {
                    node.Add("normal", ValueString("#" + image.sprite.name + ".png"));
                }
            }
        }
    }
    private void AddingNodeParam(Dictionary<string, object> node, Transform _transform)
    {
        GameObject gameObject = _transform.gameObject;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        // node基本属性
        // id 默认名称不用赋值
        List<String> defaultName = new List<string>();
        defaultName.Add("Image");
        defaultName.Add("Text");
        defaultName.Add("Button");

        if (!defaultName.Contains(gameObject.name))
        {
            node.Add("id", ValueString(gameObject.name));
        }

        // type 类型处理
        ProcessTypeElement(node, _transform);
        // 锚点和坐标
        SetAlignParam(node, _transform);
        //  size
        if (rectTransform.sizeDelta.x > 0 || rectTransform.sizeDelta.y > 0)
        {
            node.Add("size", "{" + (int)rectTransform.sizeDelta.x + "," + (int)rectTransform.sizeDelta.y + "}");
        }

        Vector3 scale = rectTransform.localScale;
        if(scale.x != 1 || scale.y != 1)
        {
            if(scale.x != scale.y)
            {
                node.Add("scale", "{" + scale.x + "," + scale.y + "}");
            }
            else
            {
                node.Add("scale",scale.x);
            }
        }

        if(gameObject.activeSelf)
        {

        }
        else
        {
            node.Add("hide",ValueString("true"));
        }
        

        // 迭代逻辑
        int childCount = transform.childCount;
        if (childCount > 0)
        {
            ArrayList child = new ArrayList();
            node.Add("children", child);
            LoadChild(_transform, child);
        }
    }

    private void AddingSpriteParam(Dictionary<string, object> node, Transform _transform)
    {
        GameObject gameObject = _transform.gameObject;
        Image image = gameObject.GetComponent<Image>();
        if(image.type == Image.Type.Sliced)
        {
            node.Add("type", ValueString("scale9sprite"));
            node.Add("scale9", ValueString("true"));
        }
        else
        {
            node.Add("type", ValueString("sprite"));  
        }
        node.Add("res", ValueString("#"+image.sprite.name+".png"));
    }

    private void AddingLabelParam(Dictionary<string, object> node, Transform _transform)
    {
        node.Add("type", ValueString("label"));
        GameObject gameObject = _transform.gameObject;
        Text text = gameObject.GetComponent<Text>();
        print(_transform.name + " " + text.text);
        node.Add("text", ValueString(text.text));
        node.Add("fontsize", text.fontSize);
        Color color = text.color;
        node.Add("color", "{" + (int)(color.r*255) + "," + (int)(color.g*255) + "," + (int)(color.b*255) + "}");

        if (gameObject.TryGetComponent<Outline>(out Outline outline)) 
        {
            Color color_outline = outline.effectColor;
            node.Add("outlineColor", "{" + (int)(color_outline.r*255) + "," + (int)(color.g*255)+","+(int)(color.b*255)+","+(int)(color.a*255)+"}");
        }
    }
}


